FastTriMain: macro
 ld   c,l               
 pop  de                
 ld   a,e               
 cp   d                 
 jr   c,@+4             
 ld   e,d               
 ld   d,a               
 ld   l,e               
 ld   h,LeftMaskAdress/256
 ld   e,[hl]            
 inc  h                 
 ld   a,[hl]            
 ld   l,d               
 ld   d,a               
 sub  [hl]              
 inc  h                 
 ld   h,[hl]            
 ld   l,c               
 ld   c,a               
 endm

DrawTriangles:
 ld   bc,5
 ld   hl,CurrentTriangl-5
DrawTriangl:            ; d still VisibleSurfaces hi-byte; bc=5
 add  hl,bc             ; pass srf,texture,p1,p2,p3
LineDrawed:
 ld   a,[nTrianglesTmp]
 dec  a
 ret  z
 ld   [nTrianglesTmp],a
 ld   e,[hl]            ; surface number
 ld   a,[de]            ; is this surface visible?
 or   a
 jr   z,DrawTriangl     ; no
 inc  l
 ld   a,[hli]           ; color number
 ld   [currentColor],a
;------------------------------------------
 ld   a,[hli]           ; pnt1
 ld   c,a
 ld   a,[hli]           ; pnt2
 ld   b,a
 ld   a,[hli]           ; pnt3
 push hl

 ld   h,RotatedPoints/256
 ld   e,a
 add  a,a               ;
 add  a,a               ; *5
 add  a,e               ;
 inc  a                 ; pass sf12,sf34 of pnt1
 inc  a
 ld   l,a
 ld   a,[hli]           ; x1
 ld   e,a
 ld   d,[hl]            ; y1

 ld   a,c               ; pnt2
 add  a,a               ;
 add  a,a               ; *5
 add  a,c               ;
 inc  a                 ; pass sf12,sf34 of pnt2
 inc  a
 ld   l,a
 ld   a,b               ; pnt3
 ld   c,[hl]            ; x2
 inc  l
 add  a,a               ;
 add  a,a               ; a=a*5
 add  a,b
 ld   b,[hl]            ; y2
 inc  a                 ; pass sf12,sf34 of pnt3
 inc  a                 ;
 ld   l,a
 ld   a,[hli]           ; x3
 ld   h,[hl]            ; y3
 ld   l,a
;-remove
 or   h
 jr   z,TriExit
 ld   a,e
 or   d
 jr   z,TriExit
 ld   a,c
 or   b
 jr   z,TriExit
;-remove end
;Sort points: in y coords order: H<D<B       
 ld   a,h                                  
 cp   d                 ; h<=d ? 
 jr   c,@+7             ; yes
 ld   h,d
 ld   d,a
 ld   a,l
 ld   l,e
 ld   e,a
 ld   a,h
 cp   b                 ; h<=b ?
 jr   c,@+7             ; yes
 ld   h,b
 ld   b,a
 ld   a,l
 ld   l,c
 ld   c,a
 ld   a,d
 cp   b                 ; d<=b ?
 jr   c,@+7             ; yes
 ld   d,b
 ld   b,a
 ld   a,e
 ld   e,c
 ld   c,a

 ld   a,b
 sub  h                 ; 
 jr   nz,TriReal
TriExit:
 pop  hl                ; hl=adress of next triangle
 ld   c,5
 ld   d,VisibleSurfaces/256
 jr   LineDrawed
TriReal:
 ld   [Tridy],a 
 ld   a,h
 add  a,a
 ld   [TriStart],a

 if 0
 ld   a,c               ; x3
 sub  l
 ld   c,a               ; x3-x1
 jr   z,dx3_0
 ld   a,e
 sub  l                 ; x2-x1
 xor  c                 ; we need signs of dx2 and dx3
 rla                    ; dx2 and dx3 to have different signs?
 ld   a,c               ; x3-x1
 jr   c,diff_signs      ; yes!
;
;------------------------------------------------------------------------------
;now we know, that (x3-x1) and (x2-x1) have same signs, it's mean two variants:
;
;         HL   HL
;      DE         DE 
;           or       
;                     
;       BC       BC
;                         let see these variants separably:
 rla                    ; is (x3-x1)>0?  right variant?
 jr   nc,RightVariant   ; yes
;Left variant:
 ld   a,c
 add  a,l
 ld   c,a               ; x3
 cp   e                 ; x3>x2?
 jr   nc,TwoLeftSides   ; yes      /i.e p2 always above p1p3/

;now variant:
;              p1
;          p2          and here need verify is p2 above p1p3 line?
;          or p2       for this if y3+dy3(x2-x3)/dx3-y2>0 
;        p3                     then p2 above=>TwoLeftSides
;
; NOTE: now (x2-x3)>0, dx3=x3-x1<0, result of dy3(x2-x3)/dx3 always in 8 bits

;let calculate dy3(x2-x3):
 push hl
 ld   a,b               ; y3
 sub  h
 ld   h,a               ; dy3=(y3-y1)>0
 ld   a,e               ; x2
 sub  c                 ; (x2-x3)>0
 ld   e,a
 ld   a,l               ; x1
 sub  c                 ; x1-x3=dx3>0
 ld   l,e               ; x2-x3
; ld   
                       
 xor  a
 rept 8
 rr   l
 jr   nc,@+3
 add  a,h
 rra
 endr
 rr   l     ; al=h*l ; a - high, l - low

 rept 8
 rl   c
 rl   a
 sub  h
 jr   nc,@+3
 add  a,h
 endr

 ld   a,c
 rla
 cpl        ; a=ac/h
 endc
 
 push hl
 push de
 push bc
 xor  a
 ld   [EdgeBufLow],a
 call BrezenEdge
 ld   a,l
 ld   [EdgeBufLow],a 
 pop  de
 pop  hl                ;
 push de                ; 
 call BrezenEdge
 pop  de
 pop  hl                ; 

 ld   a,1
 ld   [EdgeBufLow],a
 call BrezenEdge
 ld   a,[Tridy]
 ld   b,a
; inc  b
 ld   [TriStack],sp
 ld   sp,EdgeBuffer
 ld   a,[TriStart]
 ld   l,a
 ld   a,[currentColor]  ; 0,1,2
 cp   1
 ld   a,[wbuf]
 jp   c,FastTriCode
 jp   z,FastTriCode+FastTri2-FastTri1
 jp   FastTriCode+FastTri3-FastTri1
;-------------------------------------
BrezenEdge:             ; in hl - point1 (l=x1,h=y1)
                        ;    de = point2 (e=x2,d=y2)
                        ;    all registers E[0..255]
 ld   a,e               ; x2>x1?
 cp   l
 jr   nc,BrezEdgeLeftToRight
 ld   a,l
 sub  e                 ; x1-x2
 ld   c,a               ; dx
 ld   a,d               ; y2
 sub  h                 ; y1
 ld   e,a               ; d1=dy
 sub  c                 ; dx<dy?
 jr   nc,brezEdge40     ; yes
 ld   d,a               ; d2=dy-dx  here <0
 ld   a,c               ; dx
 srl  a                 ; dx/2
 cpl                    ; a=-dx/2
 inc  a                 ;
 ld   b,a
 ld   a,$7f
 sub  c                 ; will 0..$7f
 ld   c,l
 push bc
;Here de=d2,d1 ; bc=dBrez,x1
 add  a,a               ; *2
 ld   c,a
 ld   l,a
BrezenEdgeOb:
 ld   h,0
 ld   b,h
 add  hl,hl             ; *4
 add  hl,hl             ; *8
 add  hl,bc             ; *10
 ld   bc,es1
BrezenEdgeObchiy:
 add  hl,bc
 pop  bc
 push hl
 ld   h,EdgeBuffer/256
 ld   a,[EdgeBufLow]
 ld   l,a
 ld   a,b
 ld   b,128
 ret

brezEdge40:             ; dx<dy && x1>x2     
 ld   a,c               ; dx                   
 ld   c,e               ; dy will counter       
 ld   e,a               ; d1=dx                 
 sub  c                 ; dx-dy<0                
 ld   d,a               ; d2=dx-dy  here <0      

 ld   a,c               ; dy
 srl  a                 ; dy/2   
 cpl                    ;-dy/2
 inc  a
 ld   b,a
 ld   a,$77
 sub  c                 ; will 0..$77 ($7f)
 ld   c,l
 push bc
;Here de=d2,d1 ; bc=dBrez,x1

 add  a,a               ; *2
 ld   c,a
 ld   l,a
 ld   h,0
 ld   b,h
 add  hl,hl             ; *4
 add  hl,hl             ; *8
 add  hl,bc             ; *10
 ld   bc,es2
 jr   BrezenEdgeObchiy

BrezEdgeLeftToRight:
 sub  l                 ; x2-x1
 ld   c,a               ; dx
 ld   a,d               ; y2
 sub  h                 ; y1
 ld   e,a               ; d1=dy
 sub  c                 
 jr   nc,.brezEdge20    ; dx<dy   ; yes

 ld   d,a               ; d2=dy-dx  here <0
 ld   a,c               ; dx
 srl  a                 ; dx/2
 cpl                    ;-dx/2
 inc  a
 ld   b,a
 ld   a,$7f
 sub  c                 ; will 0..$7f
 ld   c,l
 push bc
;Here de=d2,d1 ; bc=dBrez,x1
 add  a,a               ; *2
 ld   c,a
 ld   l,a
 ld   h,0
 ld   b,h
 add  hl,hl             ; *4
 add  hl,hl             ; *8
 add  hl,bc             ; *10
 ld   bc,es3
 jr   BrezenEdgeObchiy

.brezEdge20:            ; dx<dy && x1<x2     
 ld   a,c               ; dx                   
 ld   c,e               ; dy
 ld   e,a               ; d1=dx                 
 sub  c                 ; dx-dy<0                
 ld   d,a               ; d2=dx-dy  here <0      

 ld   a,c               ; dy
 srl  a                 ; dy/2  
 cpl                    ;-dy/2
 inc  a
 ld   b,a
 ld   a,$77
 sub  c                 ; will 0..$77 ($7f)
 ld   c,l
 push bc
;Here de=d2,d1 ; bc=dBrez,x1
 add  a,a               ; *2
 ld   c,a
 ld   l,a
 ld   h,0
 ld   b,h
 add  hl,hl             ; *4
 add  hl,hl             ; *8
 add  hl,bc             ; *10
 ld   bc,es4
 jr   BrezenEdgeObchiy

FastTriCodeIni:
 rst  40
 db   %00111111
 dw   FastTriEnd-FastTriStart ; len
 dw   FastTriCode
 dw   FastTriStart
 db   $50               ; CopyHLtoDE

 ld   de,LeftMaskAdress ; if will have many ROM, then let save RAM
 ld   hl,leftmsk
 call putMask
 ld   a,e
 rra
 rra
 rra
 and  $1f
 ld   [de],a
 inc  e
 jr   nz,@-8
 inc  d
 ld   hl,leftmsk+8
putMask:
 ld   b,32
 push hl
 ld   c,8
 ld   a,[hli]
 ld   [de],a
 inc  de
 dec  c
 jr   nz,@-4
 pop  hl
 dec  b
 jr   nz,@-11
 ret


;---------------------------------------------------------------
; this code (FastTriCode,BrezenEdges) will at Internal RAM pages
; after initialization ;This code is automodifycied, so strongly in RAM
;
FastTriStart:
FastTri1:               ; color: 1,0
 ld   [FastTriCode+ffbuf1-FastTri1-1],a
 FastTriMain
 ld   a,0
ffbuf1:
 add  a,d               
 ld   d,h               
 ld   h,a               
 ld   a,c               
 or   a                 
 jr   z,oneAdress1
 add  a,$0f             
 add  a,a
 add  a,a               
 ld   [FastTriCode+ffmjr1-FastTri1-1],a
 ld   a,e               
 or   [hl]              ; 
 ld   [hli],a
 ld   a,e
 cpl
 and  [hl]     
 ld   [hld],a
 inc  h
 ld   e,$ff
 xor  a
 db   24,0
ffmjr1:
 rept 14
 ld   [hl],e
 inc  l
 ld   [hld],a
 inc  h
 endr
oneAdress1:
 ld   a,e               
 and  d                 ;
 ld   e,a
 or   [hl]              
 ld   [hli],a
 ld   a,e
 cpl
 and  [hl]     
 ld   [hli],a           
 dec  b
 jr   nz,FastTri1+3
 jr   FastCodeExit
;-----------------------
FastTri2:               ; color: 0,1
 ld   [FastTriCode+ffbuf2-FastTri1-1],a
 FastTriMain
 ld   a,0
ffbuf2:
 add  a,d               
 ld   d,h               
 ld   h,a               
 ld   a,c               
 or   a                 
 jr   z,oneAdress2
 add  a,$0f             
 add  a,a
 add  a,a               ; *4
 ld   [FastTriCode+ffmjr2-FastTri1-1],a
 ld   a,e
 cpl
 and  [hl]     
 ld   [hli],a
 ld   a,e               
 or   [hl]              ; 
 ld   [hld],a
 inc  h
 ld   e,$ff
 xor  a
 db   24,0
ffmjr2:
 rept 14
 ld   [hli],a
 ld   [hl],e
 dec  l
 inc  h
 endr
oneAdress2:
 ld   a,e               
 and  d                 ;
 ld   e,a
 cpl
 and  [hl]     
 ld   [hli],a
 ld   a,e               
 or   [hl]              ; 
 ld   [hli],a           
 dec  b
 jr   nz,FastTri2+3
FastCodeExit:
 ld   hl,TriStack
 ld   a,[hli]
 ld   h,[hl]
 ld   l,a
 ld   sp,hl
 pop  hl                
 ld   c,5
 ld   d,VisibleSurfaces/256
 jp   LineDrawed
;------------------------
FastTri3:               
 ld   [FastTriCode+ffbuf3-FastTri1-1],a
 FastTriMain
 ld   a,0
ffbuf3:
 add  a,d               
 ld   d,h               
 ld   h,a               
 ld   a,c               
 or   a                 
 jr   z,oneAdress3
 add  a,$0f             
 ld   c,a
 add  a,a
 add  a,c               ; *3
 ld   [FastTriCode+ffmjr3-FastTri1-1],a
 ld   a,e
 or   [hl]     
 ld   [hli],a
 ld   a,e               
 or   [hl]              ; 
 ld   [hld],a
 inc  h
 ld   a,$ff
 ld   e,a
 db   24,0
ffmjr3:
 rept 14
 ld   [hli],a
 ld   [hld],a
 inc  h
 endr
oneAdress3:
 ld   a,e               
 and  d                 ;
 ld   e,a
 or   [hl]     
 ld   [hli],a
 ld   a,e               
 or   [hl]              ; 
 ld   [hli],a           
 dec  b
 jr   nz,FastTri3+3
 jr   FastCodeExit
FastTriEnd:

leftmsk:
 db 255,127,63,31,15,7,3,1      
 db 128,192,224,240,248,252,254,255

;SECTION "texTriEnd",CODE[$7fff],BANK[textTriangl]
; db textTriangl